package com.gw.quotes.net.service;

import java.io.IOException;

import org.ksoap2.SoapEnvelope;
import org.ksoap2.SoapFault;
import org.ksoap2.serialization.SoapObject;
import org.ksoap2.serialization.SoapSerializationEnvelope;
import org.ksoap2.transport.HttpTransportSE;
import org.xmlpull.v1.XmlPullParserException;

import android.os.Handler;
import android.os.Message;

import com.gw.quotes.constant.Constant;
import com.gw.quotes.net.BaseServiceInter;
import com.gw.quotes.net.HttpCallBack;
import com.gw.quotes.net.NewException;
import com.gw.quotes.net.Request;
import com.gw.quotes.net.Response;

public abstract class WebBaseServiceImpl implements BaseServiceInter {

	// 当出现IOException 时可能是网路不稳定的原因，进行10次重复提交每次间隔0.3秒
	public static final int REPEAT = 10;
	public static final int REPEAT_SLEEP = 300;// 重复提交每次间隔0.3秒

	private int timeout = 30000;// 设置30秒延时

	// 命名空间
	protected String nameSpace = "http://service.webservice.mk.com/";

	// 调用的方法名称
	protected String methodName = "";

	// EndPoint 218.108.220.228:9080 gposinterface
	protected String endPoint = Constant.SERVER_URL;
	
	// SOAP Action
	protected String soapAction = "";

	private Response response;

	/**
	 * 修改response指向的对象
	 * @param response
	 */
	public void setResponse(Response response) {
		this.response = response;
	}

	@Override
	public Response handler(Request request, HttpCallBack callback) {
		try {
			initResponse();//初始化Response对象
			checkParam(request);//检查参数合法性
			execute(request, callback);//执行request命令
		} catch (NewException e) {
			//异常处理
			response.setResult(e.getExceptionCode());
			response.setMsg(e.getReason());
			if (callback != null) {
				callback.onFinished(response);
			}
		}
		return response;
	}

	/**
	 * 执行过程
	 * @param request
	 * @param callback
	 * @throws NewException
	 */
	public void execute(final Request request, final HttpCallBack callback)
			throws NewException {
		final Handler handler = new Handler() {
			public void dispatchMessage(Message msg) {
				if (callback != null) {
					callback.onFinished(response);
				}
			};
		};
		Runnable runnable = new Runnable() {
			int repeat = REPEAT;

			@Override
			public void run() {
				Message msg = handler.obtainMessage();
				while (repeat-- > 0) {
					try {
						System.out.println("repeat:" + repeat);
						execute_call(request);
						break;
					} catch (Exception e) {
						e.printStackTrace();
						if (e instanceof NewException) {
							NewException newException = (NewException) e;
							response.setResult(newException.getExceptionCode());
							response.setMsg(newException.getReason());
						} else {
							if (e instanceof IOException) {
								if (repeat > 0) {
									try {
										Thread.sleep(REPEAT_SLEEP);
									} catch (InterruptedException e1) {
										e1.printStackTrace();
										continue;
									}
									continue;
								} else {
									response.setResult(Response.RESULT_ERROR);
									response.setMsg("网络异常！");
								}

							} else {
								response.setResult(Response.RESULT_ERROR);
								response.setMsg(e.getMessage());
							}
						}
						break;
					}
				}
				handler.sendMessage(msg);
			}
		};
		new Thread(runnable).start();

	}

	
	/**
	 * 调用webservice请求
	 * @param request
	 * @throws NewException
	 * @throws SoapFault
	 * @throws IOException
	 */
	public void execute_call(Request request)
			throws NewException, SoapFault, IOException {
		// String nameSpace = "http://service.webservice.mk.com/";
		// String methodName = "verifyuser";
		String methodName = getMethodName();
		// String endPoint =
		// "http://219.82.140.65:9080/gposi/ws/GposWebService";
		String soapAcion = "";

		// 指定webservice的命名空间和调用的方法
		SoapObject soapObject = new SoapObject(nameSpace, methodName);

		// 添加需要的参数
		// soapObject.addProperty("arg0", "hzdt");
		// soapObject.addProperty("arg1", "1");
		setParamByRequest(request, soapObject);

		SoapSerializationEnvelope envelope = new SoapSerializationEnvelope(
				SoapEnvelope.VER11);
		envelope.setOutputSoapObject(soapObject);
		envelope.bodyOut = soapObject;
		// envelope.dotNet = true; //对dotnet
		// webservice协议的支持,如果dotnet的webservice
		// //不指定rpc方式则用true否则要用false

		// HttpTransportSE A J2SE based HttpTransport layer.
		HttpTransportSE transportSE = new HttpTransportSE(endPoint, timeout);

		try {
			transportSE.debug = true;
			transportSE.call(soapAcion, envelope);
			System.out.println(transportSE.requestDump);
			System.out.println(transportSE.responseDump);
		} catch (XmlPullParserException e) {
			e.printStackTrace();
			throw new NewException(Response.RESULT_ERROR, "XmlPullParser错误");
		}

		// 如果服务器返回的是byte[]类型：读取结果
		// SoapFault object = (SoapFault) envelope.bodyIn;
		// String result = object.getProperty(0).toString();

		// 如果服务器返回的是String类型：
		// 第6步：使用getResponse方法获得WebService方法的返回结果
		// SoapObject soapObject_response = (SoapObject) envelope.getResponse();
		if(envelope.getResponse() != null)
		{
			System.out.println("返回结果: " + envelope.getResponse().toString());
		}
		updateResponse(envelope.getResponse());
		// 通过getProperty方法获得Product对象的属性值
		// String result = "产品名称：" + soapObject_response.getProperty("name");
		// result += "产品数量：" + soapObject_response.getProperty("productNumber");
		// result += "产品价格：" + soapObject_response.getProperty("price");
	}

	
	/**
	 * 初始化 
	 */
	public void initResponse() {
		response=setResponse();
		if(response==null){
			response=new Response();
		}
	}
	
	/**
	 * result转换成response
	 * 
	 * @param response
	 */
	public void updateResponse(Object object)
			throws NewException {
		// 获取返回的结果
		if (object == null) {
			new NewException(Response.RESULT_ERROR, "无结果返回Null");
			return;
		}
		resolveResponse(object, response);
	}
	
	
	/**
	 * 请设置需要返回的Response对象
	 * @return
	 */
	public abstract Response setResponse();
	
	/**
	 * 检查参数
	 * 
	 * @param request
	 * @throws NewException
	 */
	public abstract void checkParam(Request request) throws NewException;

	/**
	 * 根据传入参数，生成json对象
	 * 
	 * @return
	 * @throws NewException
	 */
	public abstract void setParamByRequest(Request request, SoapObject rpc)
			throws NewException;


	/**
	 * 将对象解析到Response中
	 * 
	 * @param object
	 * @param response
	 */
	public abstract void resolveResponse(Object object, final Response response)
			throws NewException;

	public abstract String getMethodName() throws NewException;

	/**
	 * 字符串判空
	 * 
	 * @param str
	 * @return
	 */
	public boolean checkNull(String str) {
		if (str == null || str.trim().equals("")) {
			return true;
		} else {
			return false;
		}
	}

	public int getTimeout() {
		return timeout;
	}

	public void setTimeout(int timeout) {
		this.timeout = timeout;
	}

}
